#include "drv_uart.h"

#include "common_debug.h"
#include "gpio_drv.h"
#include "uart_drv.h"

#include <stdio.h>

/**
 * @brief UART引脚路由
 *
 */
typedef struct
{
    GPIO_Type     *tx_port; /*!< UART TX引脚端口 */
    uint32_t       tx_pin;  /*!< UART TX引脚编号 */
    GPIO_Type     *rx_port; /*!< UART RX引脚端口 */
    uint32_t       rx_pin;  /*!< UART RX引脚编号 */
    gpio_pin_mux_t mux;     /*!< UART 引脚复用 */
} snf_uart_pin_route_t;

/**
 * @brief UART硬件实例管理
 *
 */
typedef struct
{
    bool            initialized;       /*!< UART实例是否初始化 */
    uart_callback_f rx_callback;       /*!< UART-Rx回调函数 */
    void           *rx_callback_param; /*!< UART-Rx回调函数参数 */
    uart_state_t    state;             /*!< UART状态 */
    UART_Type      *uartX_addr;        /*!< UART实例地址 */
} snf_uart_hw_manager_t;

static result_e   snf_drv_uart_validate_instance(snf_uart_instance_e instance);
static UART_Type *snf_drv_uart_get_hw_instance_addr(uint32_t hw_instance);
static uint32_t   snf_drv_uart_get_hw_instance(snf_uart_instance_e uart_instance);
static void       snf_drv_uart_config(const snf_uart_config_t *uart_config);
static void       snf_drv_uart_gpio_init(const snf_uart_config_t *uart_config);
static void       snf_drv_uart_callback(uint32_t instance, uart_event_t event, void *param);

/**
 * @brief UART基础配置
 *
 */
static uart_config_t uart_base_config = {
    .oversampleRate  = UART_OVERSAMPLE_16,
    .wordLength      = UART_WORD_LEN_8BIT,
    .parityMode      = UART_PARITY_DISABLED,
    .stopBitCount    = UART_ONE_STOP_BIT,
    .rxIdleIntEnable = true,
    .transferType    = UART_USING_INTERRUPT,
    .rxDMAChannel    = 3U,
    .txDMAChannel    = 4U,
};

/* UART引脚配置表 */
static const snf_uart_pin_route_t uart_pin_route_table[UART_INSTANCE_MAX] = {
    [UART_INSTANCE_UART0_0] = { GPIOC, 3, GPIOC, 2, GPIO_PIN_MUX_FUN4 },
    [UART_INSTANCE_UART0_1] = { GPIOB, 1, GPIOB, 0, GPIO_PIN_MUX_FUN4 },
    [UART_INSTANCE_UART0_2] = { GPIOC, 9, GPIOC, 8, GPIO_PIN_MUX_FUN5 },
    [UART_INSTANCE_UART1_0] = { GPIOE, 5, GPIOE, 4, GPIO_PIN_MUX_FUN4 },
    [UART_INSTANCE_UART1_1] = { GPIOA, 3, GPIOA, 2, GPIO_PIN_MUX_FUN5 },
    [UART_INSTANCE_UART1_2] = { GPIOA, 1, GPIOA, 0, GPIO_PIN_MUX_FUN3 },
    [UART_INSTANCE_UART1_3] = { GPIOA, 11, GPIOA, 10, GPIO_PIN_MUX_FUN6 },
    [UART_INSTANCE_UART2_0] = { GPIOD, 1, GPIOD, 0, GPIO_PIN_MUX_FUN4 },
    [UART_INSTANCE_UART2_1] = { GPIOD, 7, GPIOD, 6, GPIO_PIN_MUX_FUN3 },
    [UART_INSTANCE_UART2_2] = { GPIOC, 9, GPIOC, 8, GPIO_PIN_MUX_FUN4 },
    [UART_INSTANCE_UART2_3] = { GPIOC, 5, GPIOC, 4, GPIO_PIN_MUX_FUN5 },
};

/* UART实例管理器集合 - 每个硬件UART实例一个管理器 */
static snf_uart_hw_manager_t uart_hw_manager_list[UART_INSTANCE_MAX] = { 0 };

/**
 * @brief 初始化UART模块
 *
 * @param  uart_config UART配置结构体指针
 * @return result_e    初始化结果
 */
result_e snf_drv_uart_init(const snf_uart_config_t *uart_config)
{
    /* 参数检查 */
    if (uart_config == NULL) {
        return RESULT_STATUS_INVALID_PARAM;
    }

    result_e result = snf_drv_uart_validate_instance(uart_config->instance);
    if (result != RESULT_STATUS_OK) {
        return result;
    }

    /* 获取硬件实例编号 */
    uint32_t hw_instance = snf_drv_uart_get_hw_instance(uart_config->instance);
    if (hw_instance >= UART_INSTANCE_MAX) {
        return RESULT_STATUS_INVALID_PARAM;
    }

    /* 保存用户回调函数和参数 */
    uart_hw_manager_list[hw_instance].rx_callback       = uart_config->rx_callback;
    uart_hw_manager_list[hw_instance].rx_callback_param = uart_config->rx_callback_param;
    uart_hw_manager_list[hw_instance].uartX_addr        = snf_drv_uart_get_hw_instance_addr(hw_instance);

    /* 配置UART模块 */
    snf_drv_uart_config(uart_config);

    /* GPIO初始化 */
    snf_drv_uart_gpio_init(uart_config);

    /* UART基础配置初始化 */
    errcode_t ret = UART_Init(hw_instance, &uart_hw_manager_list[hw_instance].state, &uart_base_config);
    if (ret != ERR_SUCCESS) {
        return RESULT_STATUS_ERROR;
    }

    /* 注册回调函数 */
    UART_InstallCallback(hw_instance, snf_drv_uart_callback, NULL);

    uart_hw_manager_list[hw_instance].initialized = true;
    return RESULT_STATUS_OK;
}

/**
 * @brief 初始化UART引脚
 *
 * @param uart_init_config   UART初始化配置结构体
 */
static void snf_drv_uart_gpio_init(const snf_uart_config_t *uart_config)
{
    /* 配置UART引脚 */
    const snf_uart_pin_route_t *uart_pin_config = &uart_pin_route_table[uart_config->instance];

    /* Tx 引脚 */
    GPIO_SetPinFunc(uart_pin_config->tx_port, uart_pin_config->tx_pin, uart_pin_config->mux);
    /* Rx 引脚 */
    GPIO_SetPinFunc(uart_pin_config->rx_port, uart_pin_config->rx_pin, uart_pin_config->mux);
}

/**
 * @brief 配置UART模块
 *
 * @param uart_config UART配置结构体指针
 */
static void snf_drv_uart_config(const snf_uart_config_t *uart_config)
{
    /* 配置UART模块 */
    uart_base_config.baudRate = uart_config->baud_rate;
}

/**
 * @brief  根据snf_uart_instance_e获取UART实例
 *
 * @param uart_instance  uart实例
 * @return uint32_t      UART HW num
 */
static uint32_t snf_drv_uart_get_hw_instance(snf_uart_instance_e uart_instance)
{
    static uint32_t instance_table[] = {
        [UART_INSTANCE_UART0_0] = 0, [UART_INSTANCE_UART0_1] = 0, [UART_INSTANCE_UART0_2] = 0,
        [UART_INSTANCE_UART1_0] = 1, [UART_INSTANCE_UART1_1] = 1, [UART_INSTANCE_UART1_2] = 1,
        [UART_INSTANCE_UART1_3] = 1, [UART_INSTANCE_UART2_0] = 2, [UART_INSTANCE_UART2_1] = 2,
        [UART_INSTANCE_UART2_2] = 2, [UART_INSTANCE_UART2_3] = 2,
    };

    return instance_table[(uint32_t)uart_instance];
}

/**
 * @brief 获取硬件UART实例地址
 *
 * @param hw_instance   UART HW num
 * @return UART_Type*    UART实例地址
 */
static UART_Type *snf_drv_uart_get_hw_instance_addr(uint32_t hw_instance)
{
    static UART_Type *uart_hw_instance_table[] = { UART0, UART1, UART2 };

    return uart_hw_instance_table[hw_instance];
}

/**
 * @brief 验证UART实例有效性
 *
 * @param instance      UART实例
 * @return result_e     验证结果, 验证成功返回RESULT_STATUS_OK, 否则返回错误码
 */
static result_e snf_drv_uart_validate_instance(snf_uart_instance_e instance)
{
    if (instance >= UART_INSTANCE_MAX) {
        return RESULT_STATUS_INVALID_PARAM;
    }
    return RESULT_STATUS_OK;
}

/**
 * @brief UART接收回调函数
 *
 * @param instance UART实例
 * @param param    回调参数
 */
static void snf_drv_uart_callback(uint32_t instance, uart_event_t event, void *param)
{
    snf_uart_hw_manager_t *uart_manager = &uart_hw_manager_list[instance];

    switch (event) {
    case UART_EVENT_RX_IDLE:
        uint32_t remaining = 0;
        UART_GetReceiveStatus(instance, &remaining);
        if (uart_manager->rx_callback != NULL) {
            uart_manager->rx_callback(instance, uart_manager->rx_callback_param);
        }
        UART_AbortReceivingData(instance);
        LOG("UART_EVENT_RX_IDLE, remaining: %d\n", remaining);
        break;
    }
}

result_e snf_drv_uart_send(snf_uart_instance_e instance, const uint8_t *data, uint32_t length)
{
    uint32_t  hw_instance = snf_drv_uart_get_hw_instance(instance);
    errcode_t ret         = UART_SendData(hw_instance, data, length);
    return ret == ERR_SUCCESS ? RESULT_STATUS_OK : RESULT_STATUS_ERROR;
}

result_e snf_drv_uart_receive(snf_uart_instance_e instance, uint8_t *data, uint32_t length)
{
    uint32_t  hw_instance = snf_drv_uart_get_hw_instance(instance);
    errcode_t ret         = UART_ReceiveData(hw_instance, data, length);
    return ret == ERR_SUCCESS ? RESULT_STATUS_OK : RESULT_STATUS_ERROR;
}
